import os

import click
import pandas as pd
import matplotlib.pyplot as plt

from . import ANALYSIS_CONFIGS
from .utils import read_config, format_percentage, format_thousandth, plot_show
from .doc_utils import ReportDocument


class FinancialAnalysis:
    def __init__(self, code, choice, data_file, overwrite=False):
        self.code = code
        self.choice = choice
        self.config_file = ANALYSIS_CONFIGS[choice]
        self.table_index, self.images, self.titles, self.fields = read_config(self.config_file)
        self.df = pd.read_csv(data_file, index_col=0)
        self.tables = {}
        self.format_tables = {}
        self.output = os.path.dirname(data_file)
        self.img_output = os.path.join(self.output, 'images')
        self.overwrite = overwrite

    def init_table(self, table_index):
        """从总数据集中提取需要的字段初始化为 DataFrame
            table_index: tables_fields 中定义的 key
        """
        t = pd.DataFrame(
            index=self.df.index,
            columns=self.fields[table_index]['columns']
        )
        t[self.fields[table_index]['auto']] = self.df[self.fields[table_index]['auto']]
        self.tables[table_index] = t
        return t

    def format_show_table(self, table_index):
        table = self.tables[table_index].copy()
        for column in table.columns:
            if column.endswith('率') or column.endswith('比例'):
                table[column] = format_percentage(table[column])
            else:
                table[column] = format_thousandth(table[column])
        self.format_tables[table_index] = table.T
        return table.T

    @staticmethod
    def _save_plot_show(path):
        plt.savefig(path, dpi=600, bbox_inches='tight')
        plt.close()

    def show_plot(self, table_index, image_index=0):
        if self.images[table_index]:
            config = self.fields[table_index]['plot'][image_index]

            params = {k: v for k, v in config.items() if k != 'columns'}
            params['t'] = self.tables[table_index][config['columns']]
            params['image_title'] = self.images[table_index][image_index]
            plot_show(**params)

            if not os.path.exists(self.img_output):
                os.makedirs(self.img_output)
            self._save_plot_show(os.path.join(self.img_output, params['image_title']))

    def save_to_doc(self, subject):
        # 输出分析报告
        start = self.tables['t1'].index[0]
        end = self.tables['t1'].index[-1]
        name = f"{self.code}{subject}{start}-{end}.docx"

        if (not self.overwrite) and os.path.exists(os.path.join(self.output, name)):
            if click.prompt(f'output/{self.code}/{name} 已存在，是否覆盖？(y/n)', default='y').lower() == 'n':
                return

        doc = ReportDocument(self, doc_name=name)
        doc.save()
        click.secho(f"\n文档 [{name}] 已输出到 [output] 目录下。", fg='green', bg='white')
        click.echo('')

    def start_analysis(self):
        if self.choice == 'debt-lie':
            self.debt_lie_analysis()
        elif self.choice == 'debt-quality':
            self.debt_quality_analysis()
        elif self.choice == 'debt-effect':
            self.debt_effect_analysis()
        elif self.choice == 'benefit':
            self.profit_analysis()
        elif self.choice == 'cash':
            self.cash_analysis()
        elif self.choice == 'all':
            self.all_analysis()

    def analysis(self, subject):
        """运行计算字段、绘图，并将分析结果输出到文档"""
        for t_index in self.table_index:
            exec(f"{t_index} = self.init_table({t_index!r})")
            exec(self.fields[t_index]["compute"], None, locals())

            click.secho(self.titles[t_index], fg='yellow')
            print(self.format_show_table(t_index), end='\n\n')

            for img_index in range(len(self.fields[t_index]['plot'])):
                self.show_plot(t_index, img_index)

        self.save_to_doc(subject)

    def debt_quality_analysis(self):
        """资产质量分析"""
        self.analysis('资产负债表-资产质量分析')

    def debt_lie_analysis(self):
        """财务造假识别"""
        for t_index in self.table_index:
            exec(f"{t_index} = self.init_table({t_index!r})")
            exec(self.fields[t_index]["compute"], None, locals())

            click.secho(self.titles[t_index], fg='yellow')
            print(self.format_show_table(t_index), end='\n\n')

            if t_index == 't6':
                tmp_df = pd.merge(self.tables[t_index]['存货占总资产的比率'],
                                  self.tables['t1']['(应收账款+合同资产)占总资产的比率'],
                                  right_index=True, left_index=True)
                image_title = self.images[t_index][0]
                plot_show(tmp_df, image_title=image_title, y_label='', y_format='')
                self._save_plot_show(os.path.join(self.img_output, image_title))
            else:
                for img_index in range(len(self.fields[t_index]['plot'])):
                    self.show_plot(t_index, img_index)

        self.save_to_doc('资产负债表-造假分析')

    def debt_effect_analysis(self):
        """看资产负债表，分析一家企业牛不牛"""
        for t_index in self.table_index:
            exec(f"{t_index} = self.init_table({t_index!r})")
            exec(self.fields[t_index]["compute"], None, locals())

            click.secho(self.titles[t_index], fg='yellow')
            print(self.format_show_table(t_index), end='\n\n')

            if t_index == 't7':
                tmp_df = pd.merge(self.tables[t_index]['存货占总资产的比率'],
                                  self.tables['t5']['应收账款加合同资产占总资产的比率'],
                                  right_index=True, left_index=True)
                image_title = self.images['t7'][0]
                plot_show(tmp_df, image_title=image_title, y_label='', y_format='')
                self._save_plot_show(os.path.join(self.img_output, image_title))
            else:
                for img_index in range(len(self.fields[t_index]['plot'])):
                    self.show_plot(t_index, img_index)
        self.save_to_doc('资产负债表-深入分析')

    def profit_analysis(self):
        """看利润表，了解企业是如何创造利润的"""
        self.analysis('利润表分析')

    def cash_analysis(self):
        """分析现金流量表"""
        self.analysis('现金流量表分析')

    def all_analysis(self):
        """三大报表综合分析"""
        for t_index in self.table_index:
            exec(f"{t_index} = self.init_table({t_index!r})")
            exec(self.fields[t_index]["compute"], None, locals())

            click.secho(self.titles[t_index], fg='yellow')
            print(self.format_show_table(t_index), end='\n\n')

            if t_index == 't8':
                tmp_df = pd.merge(self.tables['t8']['存货占总资产的比率'],
                                  self.tables['t5']['(应收账款+合同资产)占总资产的比率'],
                                  right_index=True, left_index=True)
                image_title = self.images['t8'][0]
                plot_show(tmp_df, image_title=image_title, y_label='', y_format='')
                self._save_plot_show(os.path.join(self.img_output, image_title))
            else:
                for img_index in range(len(self.fields[t_index].get('plot', []))):
                    self.show_plot(t_index, img_index)
        self.save_to_doc('财务报表综合分析')
